package br.com.lambdacore.lang;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;

import org.apache.commons.lang.builder.ToStringStyle;

import br.com.lambdacore.lang.annotation.ToString;
import br.com.lambdacore.lang.reflect.AnnotationUtils;
import br.com.lambdacore.validator.Validator;

public class ToStringBuilder extends
		org.apache.commons.lang.builder.ToStringBuilder {

	public ToStringBuilder(Object thiz) {
		super(thiz);
		this.init(thiz);
	}

	public ToStringBuilder(Object thiz, ToStringStyle style) {
		super(thiz, style);
		this.init(thiz);
	}

	@SuppressWarnings("unchecked")
	private void init(Object thiz) {
		try {
			Collection<Field> fields = AnnotationUtils.getAllFieldsAnnoted(
					thiz.getClass(), ToString.class);
			for (Field field : fields) {
				field.setAccessible(true);
				ToString toString = field.getAnnotation(ToString.class);
				String name = this.getFieldName(field, toString);
				Object obj = this.getValue(thiz, field, toString);
				this.append(name, obj);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private String getFieldName(Field field, ToString toString) {
		return (!toString.value().equals("")) ? toString.value() : field
				.getName();
	}

	private Object getValue(Object thiz, Field field, ToString toString)
			throws IllegalAccessException, SecurityException,
			NoSuchFieldException {
		Object object = field.get(thiz);
		String fieldName = toString.field();
		if (Validator.is(fieldName).notNullOrBlank()) {
			Field field2 = object.getClass().getDeclaredField(fieldName);
			field2.setAccessible(true);
			object = field2.get(object);
		}
		return object;
	}

	public static ToStringBuilder newInstance(Object thiz) {
		return new ToStringBuilder(thiz);
	}

	public static ToStringBuilder newInstance(Object thiz, ToStringStyle style) {
		return new ToStringBuilder(thiz, style);
	}

}
